package org.andao.security.filter;

import static javax.servlet.http.HttpServletResponse.SC_UNAUTHORIZED;

import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.andao.core.utils.WrappedRequest;
import org.andao.security.rest.AuthenticationResult;
import org.andao.security.rest.HmacAttributes;
import org.andao.security.rest.HttpRequestSiningHelper;
import org.andao.security.rest.RequestSignatureException;
import org.andao.security.rest.AuthenticationResult.Status;
import org.andao.security.service.impl.UserServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.ui.FilterChainOrder;
import org.springframework.security.ui.SpringSecurityFilter;


/**
 * 用于REST API的用户认证.
 * 
 * @author Seewo Software - Marco.hu(huzhiguo@cvte.cn)
 * 
 */
public class RESTApiAuthenticationFilter extends SpringSecurityFilter{

	@Autowired
	@Qualifier("userService")
	private UserServiceImpl userServie;
	
	@Override
	public int getOrder() {
		return FilterChainOrder.ANONYMOUS_FILTER;
	}

	@Override
	protected void doFilterHttp(HttpServletRequest request,	HttpServletResponse response, FilterChain chain)
			throws IOException, ServletException {

		if (!HttpRequestSiningHelper.hasSignature(request)) {
			chain.doFilter(request, response);
		} else {
			try {
				WrappedRequest wrappedRequest = WrappedRequest.wrap(request);
				debugLog(wrappedRequest);
				
				AuthenticationResult result = userServie.determineRESTRequest(wrappedRequest);
				
				if (result.getStatus() == Status.FAIL) {
					response.sendError(SC_UNAUTHORIZED);
					logger.warn("REST请求签名验证失败.");
					return;
				}

				if (result.getStatus() == Status.SUCCESS) {
					logger.debug("REST请求签名校验成功.Username:"+result.getUsername());					
					wrappedRequest.setAttribute(HmacAttributes.X_AUTHENTICATED_USERNAME,result.getUsername());					
				}
				chain.doFilter(wrappedRequest, response);
			} catch (Exception e) {
				logger.error("REST请求签名错误:"+e.fillInStackTrace());
				throw new RequestSignatureException(e);
			}

		}
	}	
	
	private void debugLog(WrappedRequest wrapped){
		if(logger.isDebugEnabled()){
			StringBuilder sb = new StringBuilder();
			sb.append("\n\n----------------------------------\n")
			.append("Validate Request:\n")
			.append("Signatur:"+HttpRequestSiningHelper.getSignature(wrapped)+"\n")
			.append("Body:"+wrapped.getBody()+"\n")
			.append("Timestamp:"+HttpRequestSiningHelper.getDateFromHeader(wrapped)+"\n")
			.append("Request URI:"+wrapped.getRequestURI()+"\n")
			.append("Method:"+wrapped.getMethod()+"\n")
			.append("\n-------------------------------------\n");
			logger.debug(sb.toString());
		}
		
	}

	

}
